#coding=utf-8
"""
Created on Wed Oct  5 11:17:12 2016

@author: zxj
"""
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor

'''
一个简单的聊天室服务器，通过继承LineReceiver协议,源自Twsited.NetWorking.Programming
'''
class ChatProtocol(LineReceiver):
    def __init__(self,factory):
        self.factory=factory
        self.name=None
        self.state='REGISTER'
        
    def connectionMade(self):
        self.sendLine("What's you name?".encode('utf-8'))
        
    def connectionLost(self,reason):
        if self.name in self.factory.users:
            del self.factory.users[self.name]
            self.broadcastMessage(str("%s has left the chanel."%(self.name)).encode('utf-8'))
    def lineReceived(self,line):  #被dataReceived()调用。
        if self.state=='REGISTER':
            self.handle_REGISTER(line)  #用户注册，在注册的过程，绑定协议工厂的用户字典中，因此协议工厂和协议实例之间往往是这样的关系
                                        #协议工光有指向协议的引用，在buildProtocol中回调，而协议同时也有指向创建本身的协议工厂的属性，为能够在
                                        #协议之间之间进行通信，协议工厂通常会存放协议的共享变量
        else:
            self.handle_CHAT(line)   #用户交流
    def handle_REGISTER(self,name):
        if name in self.factory.users:
            self.sendLine('Name taken,please choose another'.encode('utf-8'))
        name=name.decode('utf-8')
        self.sendLine(str("Welcome,%s"%(name,)).encode('utf-8'))
        self.broadcastMessage(str("%s has joined the channel"%(name,)).encode('utf-8'))
        self.name=name
        self.factory.users[name]=self
        self.state='CHAT'
    def handle_CHAT(self,message):
        message=message.decode('utf-8')
        message=str("<%s> %s"%(self.name,message)).encode('utf-8')
        self.broadcastMessage(message)
    def broadcastMessage(self,message):#向所有用户广播，每个协议实例与特定的将会与transport通道绑定在一起。一个协议实例将会对应一个会话。
        for name,protocol in self.factory.users.items():
            if protocol !=self:
                protocol.sendLine(message)
class ChatFactory(Factory):
    def __init__(self):
        self.users={}   #Twsited是通过协议工厂来创建实例的。协议工厂不仅可以创建协议，与此同时，也可以实现协议实例之间通信。如在协议工厂中创建共享变量。

    def buildProtocol(self,addr):
        return ChatProtocol(self)
 
        
if '__name__'=='__main__':
    reactor.listenTCP(8000,ChatFactory())
    reactor.run()
                
